import os

from settings import (IMAGES_EXTENSIONS, THUMBNAIL_EXP, IMAGES_EXTENSIONS,
		      IMAGES_ROOT_FOLDER, MEDIA_ROOT, INSTALLED_APPS,
		      ADMIN_BASE_URL, ADMIN_SERVERSIDE_URL)

from models import Folder, Image

def find_root():
    """ Finds the root folder.
    """
    try:
	return Folder.objects.get(sup_folder=None)
    except Folder.DoesNotExist:
	# The user has never synchronized tthe filesystem
	# or root folder has disappeared.
	return None


def make_menu(current_url):
    """ Builds a menu with all djips applications.
    """
    menu = {}    
    current_module_found = False

    for app in INSTALLED_APPS:
	try:
	    exec "from %s import djips_admin" % app
	except:
	    continue

	if 'menu_title' in dir(djips_admin):
	    title = djips_admin.menu_title
	else:
	    title = app

	# Check if the page currently called belong to this app
	# Special case: we call the index (so the page does not
	# specify which module is called.
	# In this case, we set djips_common as the active page.
	# The menu type can have three possible values:
	# - 'before' for apps found before the current one
	# - 'current' for the current one
        # - 'after' for the following ones
	if current_url.startswith(ADMIN_SERVERSIDE_URL + '/' + app) or \
		current_url == ADMIN_SERVERSIDE_URL and app == 'djips_common':
	    current_module_found = True
	    menu_type = 'current'
	else:
	    menu_type = current_module_found and 'before' or 'after'

	if 'make_menu' in dir(djips_admin):
	    # Adds a third element to the menu tuple to determine the active
	    # page.
	    menu[(title, app, menu_type)] = \
		[(name, url, current_url.startswith(url))
		 for name, url in djips_admin.make_menu()]

    return menu


def split_name(name):
    """ Returns a tuple (name, extension) from a filename.

    >>> split_name('')
    ('', '')

    >>> split_name('no_extension')
    ('no_extension', '')

    >>> split_name('file.jpg')
    ('file', 'jpg')

    >>> split_name('file.1.jpg')
    ('file.1', 'jpg')

    Yes it does not really work for tar.gz, but that's definitelly
    not a good image format ;)    
    >>> split_name('file.tar.gz')
    ('file.tar', 'gz')
    
    """

    split = name.split('.')
    if len(split) == 1:
        return (name, '')

    return ('.'.join(split[:-1]), split[-1])


def sync_filesystem(folder):
    """ Explore content of 'folder' and synchronise the database
    with it.
    """
    new_folders = []
    new_images = []
    deleted_folders = []
    deleted_images = []

    default_thumbnail = 'djips/images/thumb_default.jpg'

    # Before creating image, we store every data in this list.
    # Each item will be composed of a dictionnary with the key
    # file, thumbnail and folder.
    # At the end, we check that the file does not correspond to
    # a thumbnail of another picture (stored in the thumb_list
    # list)
    images_list = []
    thumb_list = []

    # We remove a possible pending slash.
    if not folder == '/' and folder.endswith('/'):
        folder = folder[:-1]

    # We check that no folder or images has been deleted.
    try:
	path = [Folder.objects.get(dir=folder)]
    except Folder.DoesNotExist:
	path = None
    while path:
	current_folder = path.pop()

	if not os.path.exists(current_folder.dir):
	    deleted_folders.append(current_folder.dir)
	    deleted_folders.extend(
		[f.dir for f in current_folder.all_folders()])
	    deleted_images.extend(
		[img.file for img in current_folder.all_images()])
	    current_folder.delete()
	else:
	    sub_folders = current_folder.sub_folders.all()
	    images = current_folder.images.all()

	    for image in images:
		 if not os.path.exists(image.file.path):
		     deleted_images.append(image.file)
		     image.delete()

            path.extend(sub_folders)

    for root, folders, files in os.walk(folder):
	# We first check that the root folder in stored in the database.
	try:
	    root_db = Folder.objects.get(dir = root)
	except Folder.DoesNotExist:
	    # We create it.
	    root_split = root.split('/')

	    if root == '/':
		# In the case that someone shares his whole harddrive.
		root_name = '/'
		root_father = None
	    else:
		root_name = root_split.pop()
		root_father_dir = '/'.join(root_split)

		try:
		    root_father = Folder.objects.get(dir = root_father_dir)
		except Folder.DoesNotExist:
		    root_father = None

	    root_db = Folder(dir = root,
			     name = root_name,
			     sup_folder = root_father)
	    root_db.save()
	    
	    # We store it as a new folder.
	    new_folders.append(root_db)


        relative_path = root.split(MEDIA_ROOT)[-1]
	# And to finish, the images.
	for file in files:
	    if file in ['', '.', '..']:
		# Should not happen.
		continue

	    file_name, file_extension = split_name(file)

	    # We check that the file is an image.
	    if not file_extension in IMAGES_EXTENSIONS:
		continue

            # We check that the corresponding thumbnail exists.
            thumbnail = THUMBNAIL_EXP % {'name': file_name,
                                         'extension' : file_extension}
            thumbnail_file = root + '/' + thumbnail
            thumbnail_relative = '/'.join([relative_path, thumbnail])

            thumbnail_exists = os.path.exists(thumbnail_file)
            if not thumbnail_exists:
                thumbnail_relative = default_thumbnail

	    try:
		image = Image.objects.get(
		    file = '/'.join([relative_path, file]))
                # We update the thumbnail if a new one is found.
                if thumbnail_exists and \
                    image.thumbnail == default_thumbnail:
                    image.thumbnail = thumbnail_relative
                    image.save()
                    new_images.append(image)
                    
	    except Image.DoesNotExist:
                images_list.append({'file': '/'.join([relative_path, file]),
                                    'thumbnail': thumbnail_relative,
                                    'folder': root_db})
                thumb_list.append(thumbnail_relative)

    # Now we check every images found to see if the
    # file is not a thumbnail of another image.
    # We also have to check in the list of already imported images.
    existing_thumb = [img.thumbnail for img in Image.objects.all()]
    
    for img in images_list:
        if img['file'] in thumb_list or \
           img['file'] in existing_thumb:
            continue
        
        image = Image(file = img['file'],
                      thumbnail = img['thumbnail'],
                      folder = img['folder'],
                      mark=-1)
        image.save()
        new_images.append(image)

    return (new_folders, new_images, deleted_folders, deleted_images)

    
